﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Data;

namespace View.Data
{
    public static class DataHelper
    {
        public static double Random(Random random, double deviation, bool positive)
        {
            int rand = random.Next(positive ? 0 : -1000000, 1000000);
            return (double)rand / 1000000 * deviation;
        }
        public static double Random(Random random, double deviation)
        {
            return Random(random, deviation, false);
        }
    }

    public struct FullFrequency
    {
        public int Frequency1;
        public int Frequency2;
        //public int Frequency3 { get; set; }
        //public int Frequency4 { get; set; }
        //public int Frequency5 { get; set; }
        //public int Frequency6 { get; set; }
        //public int Frequency7 { get; set; }
        //public int Frequency8 { get; set; }
        //public int Frequency9 { get; set; }
        //public int Frequency10 { get; set; }
        //public int Frequency11 { get; set; }
        //public int Frequency12 { get; set; }

        //public int Total { get; set; }
    }
    public class Data
    {
        public DateTime Date { get; set; }
        public decimal Total { get; set; }
        public string Category { get; set; }    //设备名称
        public int DevNo { get; set; }          //设备序号
        public string Product { get; set; }     //
        public string Year { get; set; }        //年
        public string Month { get; set; }       //月
        public int Frequency { get; set; }      //次数
        public int Duration { get; set; }       //时间

        public int Frequency1 { get; set; }
        public int Frequency2 { get; set; }
        public int Frequency3 { get; set; }
        public int Frequency4 { get; set; }
        public int Frequency5 { get; set; }
        public int Frequency6 { get; set; }
        public int Frequency7 { get; set; }
        public int Frequency8 { get; set; }
        public int Frequency9 { get; set; }
        public int Frequency10 { get; set; }
        public int Frequency11 { get; set; }
        public int Frequency12 { get; set; }

        public FullFrequency TotalFrequency { get; set; }


        public static string DataSourceName { get { return "Default Datasource"; } }

        public static List<Data> GetStaticDataList()
        {
            List<Data> list = new List<Data>();

            DateTime baseDate = new DateTime(2011, 1, 1);
            Random r = new Random();
            for (int j = 2011; j <= 2013; j++)
            {
                for (int i = 1; i <= 12; i++)
                {
                    for (int m = 1; m <= 50; m++)
                    {
                        string strM = i.ToString();
                        switch (i)
                        {
                            case 1:
                                strM = "一月";
                                break;
                            case 2:
                                strM = "二月";
                                break;
                            case 3:
                                strM = "三月";
                                break;
                            case 4:
                                strM = "四月";
                                break;
                            case 5:
                                strM = "五月";
                                break;
                            case 6:
                                strM = "六月";
                                break;
                            case 7:
                                strM = "七月";
                                break;
                            case 8:
                                strM = "八月";
                                break;
                            case 9:
                                strM = "九月";
                                break;
                            case 10:
                                strM = "十月";
                                break;
                            case 11:
                                strM = "十一月";
                                break;
                            case 12:
                                strM = "十二月";
                                break;
                            default:
                                break;

                        }

                        list.Add(new Data()
                        {
                            Date = baseDate,
                            Year = j.ToString(),
                            Month = strM,
                            Category = "SII" + m.ToString(),
                            Frequency = r.Next(m * j) * j - r.Next(j) * j,
                            Duration = r.Next(m * 20),
                            Frequency1 = r.Next(m * 20),
                            Frequency2 = r.Next(m * 20),
                            Frequency3 = r.Next(m * 20),
                            Frequency4 = r.Next(m * 20),
                            Frequency5 = r.Next(m * 20),
                            Frequency6 = r.Next(m * 20),
                            Frequency7 = r.Next(m * 20),
                            Frequency8 = r.Next(m * 20),
                            Frequency9 = r.Next(m * 20),
                            Frequency10 = r.Next(m * 20),
                            Frequency11 = r.Next(m * 20),
                            Frequency12 = r.Next(m * 20)

                        });
                    }

                    baseDate = baseDate.AddMonths(1);
                }
            }

            return list;
        }

        public static List<Data> GetRandomDataList(int maxRowCount)
        {
            List<Data> list = new List<Data>();
            string[] catergories = new string[] { "Category 1", "Category 2", "Category 3", "Category 4" };
            string[] products = new string[] { "Aaa", "Bbb", "Ccc", "Ddd", "Eee", "Fff" };
            Random r = new Random();

            DateTime date = DateTime.Today;
            int rowCount = r.Next(maxRowCount);
            if (rowCount < 50)
                rowCount = 50;

            for (int i = 0; i < rowCount; i++)
            {
                date = date.AddDays(r.Next(8));
                list.Add(new Data()
                {

                    Date = date,
                    Total = 3500 - r.Next(1000),
                    Category = catergories[r.Next(catergories.Length)],
                    Product = products[r.Next(products.Length)]
                });
            }


            return list;
        }

        public static DataTable GetDataTable()
        {
            DataTable dt = CreateTable();
            foreach (Data d in GetRandomDataList(150))
                dt.Rows.Add(new object[] { d.Date, d.Total, d.Category, d.Product });
            return dt;
        }

        private static DataTable CreateTable()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Date", typeof(DateTime));
            dt.Columns.Add("Total", typeof(float));
            dt.Columns.Add("Category", typeof(string));
            dt.Columns.Add("Product", typeof(string));
            return dt;
        }
    }

    public class ProductClass
    {
        readonly List<int> productIDs = new List<int>();
        readonly decimal? minPrice;
        readonly decimal? maxPrice;
        readonly double saleProbability;

        public double SaleProbability { get { return saleProbability; } }

        public ProductClass(decimal? minPrice, decimal? maxPrice, double saleProbability)
        {
            this.minPrice = minPrice;
            this.maxPrice = maxPrice;
            this.saleProbability = saleProbability;
        }
        public bool AddProduct(int productID, decimal price)
        {
            bool satisfyMinPrice = !minPrice.HasValue || price >= minPrice.Value;
            bool satisfyMaxPrice = !maxPrice.HasValue || price < maxPrice.Value;
            if (satisfyMinPrice && satisfyMaxPrice)
            {
                productIDs.Add(productID);
                return true;
            }
            return false;
        }
        public bool ContainsProduct(int productID)
        {
            return productIDs.Contains(productID);
        }
    }

    public class ProductClasses : List<ProductClass>
    {
        public new ProductClass this[int productID]
        {
            get
            {
                foreach (ProductClass productClass in this)
                    if (productClass.ContainsProduct(productID))
                        return productClass;
                throw new ArgumentException("procutID");
            }
        }

        public ProductClasses(ICollection products)
        {
            Add(new ProductClass(null, 100m, 0.5));
            Add(new ProductClass(100m, 500m, 0.4));
            Add(new ProductClass(500m, 1500m, 0.3));
            Add(new ProductClass(1500m, null, 0.2));
            foreach (DataRow product in products)
            {
                int productID = (int)product["ProductID"];
                decimal listPrice = (decimal)product["ListPrice"];
                foreach (ProductClass productClass in this)
                    if (productClass.AddProduct(productID, listPrice))
                        break;
            }
        }
    }

    public class RegionClasses : Dictionary<int, double>
    {
        public RegionClasses(ICollection regions)
        {
            int? numberEmployeesMin = null;
            foreach (DataRow region in regions)
            {
                short numberEmployees = (short)region["NumberEmployees"];
                numberEmployeesMin = numberEmployeesMin.HasValue ? Math.Min(numberEmployeesMin.Value, numberEmployees) : numberEmployees;
            }
            foreach (DataRow region in regions)
                Add((int)region["RegionID"], (short)region["NumberEmployees"] / (double)numberEmployeesMin.Value);
        }
    }

    public class UnitsSoldRandomGenerator
    {
        const int MinUnitsSold = 5;

        readonly Random rand;
        readonly int startUnitsSold;
        int? prevUnitsSold;
        int? prevPrevUnitsSold;
        int unitsSold;
        int unitsSoldTarget;
        bool isFirst = true;

        public int UnitsSold { get { return unitsSold; } }
        public int UnitsSoldTarget { get { return unitsSoldTarget; } }

        public UnitsSoldRandomGenerator(Random rand, int startUnitsSold)
        {
            this.rand = rand;
            this.startUnitsSold = Math.Max(startUnitsSold, MinUnitsSold);
        }
        public void Next()
        {
            if (isFirst)
            {
                unitsSold = startUnitsSold;
                isFirst = false;
            }
            else
            {
                unitsSold = unitsSold + (int)Math.Round(DataHelper.Random(rand, unitsSold * 0.5));
                unitsSold = Math.Max(unitsSold, startUnitsSold);
            }
            int unitsSoldSum = unitsSold;
            int count = 1;
            if (prevUnitsSold.HasValue)
            {
                unitsSoldSum += prevUnitsSold.Value;
                count++;
            }
            if (prevPrevUnitsSold.HasValue)
            {
                unitsSoldSum += prevPrevUnitsSold.Value;
                count++;
            }
            unitsSoldTarget = (int)Math.Round((double)unitsSoldSum / count);
            prevPrevUnitsSold = prevUnitsSold;
            prevUnitsSold = unitsSold;
        }
    }
}
